# -*- coding: utf-8 -*-
# created on 2016/9/28

from mathsolver.functions.base import *
from sympy import simplify, sqrt, pi
from mathsolver.functions.sympy_utils import safe_degree
from mathsolver.functions.zhixian.base import default_symbols


def peifang(expr, sym):
    expr = expr.expand()
    if expr.is_Pow and expr.args[1] == 2:
        return expr

    if expr.is_Add:
        a, h = expr.as_independent(sym)
    else:
        a, h = S.Zero, expr

    if h.coeff(sym ** 2).is_Number and h.coeff(sym) == 0:
        return expr

    if safe_degree(h, sym) == 2 and h.is_Add:
        coeff_yici = 0
        coeff_erci = 0
        for arg in h.args:
            if safe_degree(arg, sym) == 1:
                coeff_yici = coeff_yici + arg / sym
            elif safe_degree(arg, sym) == 2:
                coeff_erci = coeff_erci + arg / (sym ** 2)

        v = coeff_yici / (2 * coeff_erci)
        return coeff_erci * (sym + coeff_yici / (2 * coeff_erci)) ** 2 + a - coeff_erci * v ** 2


class Yuan(object):
    def __init__(self, eq):
        self.eq = eq.sympify()
        self.generalizedEq = self.generalized()
        self.normalizedEq = self.normalized()
        self.A, self.B, self.D, self.E, self.F = self.get_coeff()
        self.radius = self.get_radius()
        self.diameter = self.get_diameter()
        self.centerPoint = self.get_center()
        self.area = self.get_area()
        self.perimeter = self.get_perimeter()

    def generalized(self):
        f1, f2 = self.eq
        expr = (f1 - f2).expand().simplify()
        symx, symy = default_symbols(expr)
        da = expr.coeff(symx ** 2)
        eq_left = simplify(expr / da)
        eq_right = S.Zero
        return BaseYuan({"name": "", "value": [eq_left, eq_right]})

    def normalized(self):
        yibanshi = self.generalizedEq.sympify()
        expr = yibanshi[0] - yibanshi[1]
        symx, symy = default_symbols(expr)
        symx_expr = S.Zero
        symy_expr = S.Zero
        constant_expr = S.Zero
        for arg in expr.args:
            arg_symbols = arg.free_symbols
            if (symx in arg_symbols) and (symy not in arg_symbols):
                symx_expr += arg
            if (symy in arg_symbols) and (symx not in arg_symbols):
                symy_expr += arg
            if (symx not in arg_symbols) and (symy not in arg_symbols):
                constant_expr += arg
        new_symx_expr = peifang(symx_expr, symx)
        da = symx_expr.coeff(symx ** 2)
        ex = new_symx_expr
        ex_cont = S.Zero
        if ex.is_Add:
            ex_cont, ex = ex.as_independent(symx)
        new_symy_expr = peifang(symy_expr, symy)
        ey = new_symy_expr
        ey_cont = S.Zero
        if ey.is_Add:
            ey_cont, ey = ey.as_independent(symy)
        new_constant = -(ex_cont + ey_cont + constant_expr)
        return BaseYuan({"name": "", "value": [ex / da + ey / da, new_constant / da]})

    def get_coeff(self):
        yibanshi = self.generalizedEq.sympify()
        expr = yibanshi[0] - yibanshi[1]
        symx, symy = default_symbols(expr)
        da = expr.coeff(symx ** 2)
        db = expr.coeff(symy ** 2)
        dd = expr.coeff(symx)
        de = expr.coeff(symy)
        df = expr - da * symx ** 2 - db * symy ** 2 - dd * symx - de * symy
        return BaseValue(da), BaseValue(db), BaseValue(dd), BaseValue(de), BaseValue(df)

    def get_center(self):
        da = self.A.sympify()
        db = self.B.sympify()
        dd = self.D.sympify()
        de = self.E.sympify()
        return BasePoint({"name": "", "value": [-dd / (2 * da), -de / (2 * db)]})

    def get_radius(self):
        da = self.A.sympify()
        db = self.B.sympify()
        dd = self.D.sympify()
        de = self.E.sympify()
        df = self.F.sympify()
        radius = sqrt(dd ** 2 / (4 * da) + de ** 2 / (4 * db) - df)
        return BaseValue(radius)

    def get_diameter(self):
        return BaseValue(2 * self.radius.sympify())

    def get_area(self):
        radius = self.radius.sympify()
        return BaseValue(pi * radius * radius)

    def get_perimeter(self):
        radius = self.radius.sympify()
        return BaseValue(2 * pi * radius)


if __name__ == '__main__':
    cc = Yuan(BaseEq(["2*x**2+2*y**2+x+y-1", "0"]))
